﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.ServiceModel;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using DiscoveryLogic.UI.Layouts.WS;

namespace DiscoveryLogic.UI.Layouts
{
    public class WSProxy
    {
        //protected static string address = "http://jaimerxpold2/fin/banking.svc"; 
        // Chris: temporarily change to our local WS
        protected static string defaultaddress = "http://localhost:49513/BankingDemo_Web/Banking.svc";

        protected static string _rootURL = string.Empty;


        protected BankingClient GetClient()
        {
            BasicHttpBinding binding = new BasicHttpBinding();
            binding.MaxReceivedMessageSize = 1000000;

            BankingClient bc = new BankingClient(binding, new EndpointAddress(address));

            return bc;
        }

        protected string address
        {
            get
            {
                return RootURL + "Banking.svc";
            }
        }
        public static string RootURL
        {
            get
            {
                if (_rootURL == string.Empty)
                {
                    string appRoot = Application.Current.Host.Source.ToString().ToUpper();

                    if (appRoot.Contains("CLIENTBIN"))
                    {
                        _rootURL = appRoot.Substring(0, appRoot.IndexOf("CLIENTBIN"));
                    }
                    else
                    {
                        _rootURL = appRoot.Substring(0, appRoot.LastIndexOf('/'));
                    }
                    _rootURL += "/";
                }


                return _rootURL;

            }
            set
            {
            }
        }

    }

    public class StatementService : WSProxy
    {


        public delegate void GetStatementsCompletedCallBack(GetStatementsCompletedEventArgs args);

        GetStatementsCompletedCallBack _GetStatementsCompletedCallBack;

        public void GetStatementAsync(GetStatementsCompletedCallBack callback)
        {
            BankingClient bc = GetClient();
            bc.GetStatementsCompleted += new EventHandler<GetStatementsCompletedEventArgs>(bc_GetStatementsCompleted);
            _GetStatementsCompletedCallBack = callback;
            bc.GetStatementsAsync();
        }

        void bc_GetStatementsCompleted(object sender, GetStatementsCompletedEventArgs e)
        {
            _statements = Convert(e.Result);
            if (this._GetStatementsCompletedCallBack != null)
                this._GetStatementsCompletedCallBack(e);



        }

        static protected Statement[] _statements;
        static public Statement[] Statements
        {
            get
            {
                if (_statements == null)
                {
                    _statements = LocalDataFiles.LoadData<Statement[]>("BankingDemo.LocalDataFiles.Statements.xml");
                }
                return _statements;
            }
        }


        private static Statement[] Convert(Statement[] source)
        {
            Statement[] target = new Statement[source.Length];

            for (int i = 0; i < source.Length; i++)
            {
                target[i] = new Statement();
                target[i].Abbreviation = source[i].Abbreviation;
                target[i].CreditAvailable = source[i].CreditAvailable;
                target[i].EndDate = source[i].EndDate;
                target[i].OverLimitAmount = source[i].OverLimitAmount;
                target[i].PaymentDueDate = source[i].PaymentDueDate;
                target[i].StartDate = source[i].StartDate;
                target[i].Title = source[i].Title;
                target[i].Transactions = Convert(source[i].Transactions);
            }

            return target;

        }

        /// <summary>
        /// Given an array of web service transaction objects,
        /// copy the data into an array of Transaction objects.
        /// Each statement has many transaction objects.
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        private static Transaction[] Convert(Transaction[] source)
        {
            Transaction[] target = new Transaction[source.Length];

            for (int i = 0; i < source.Length; i++)
            {
                target[i] = new Transaction();
                target[i].Amount = source[i].Amount;
                target[i].Balance = source[i].Balance;
                target[i].Date = source[i].Date;
                target[i].Deposit = source[i].Deposit;
                target[i].Description = source[i].Description;
                target[i].InfoTreatmentIndicator = source[i].InfoTreatmentIndicator;
                target[i].Withdrawal = source[i].Withdrawal;
            }

            return target;

        }
    }

    public class MortgageService : WSProxy
    {

        public delegate void GetMortgageCompletedCallBack(GetMortgageCompletedEventArgs args);
        GetMortgageCompletedCallBack _GetMortgageCompletedCallBack;


        static protected DiscoveryLogic.DataServices.DataSources.MortgageAccount _account;


        public void GetMortgageAsync(GetMortgageCompletedCallBack callback)
        {
            BankingClient bc = GetClient();
            bc.GetMortgageCompleted += new EventHandler<GetMortgageCompletedEventArgs>(bc_GetMortgageCompleted);
            _GetMortgageCompletedCallBack = callback;
            bc.GetMortgageAsync();
        }

        static public DiscoveryLogic.DataServices.DataSources.MortgageAccount Account
        {
            get
            {
                return _account;
            }
        }

        void bc_GetMortgageCompleted(object sender, GetMortgageCompletedEventArgs e)
        {
            _account = Convert(e.Result);

            GetMortgageCompletedCallBack callback = _GetMortgageCompletedCallBack;

            if (callback != null)
            {
                if (callback != null)
                    callback(e);
            }
        }


        private static DiscoveryLogic.DataServices.DataSources.MortgageAccount Convert(MortgageAccount source)
        {

            DiscoveryLogic.DataServices.DataSources.MortgageAccount target = new DiscoveryLogic.DataServices.DataSources.MortgageAccount();
            target.AccountNumber = source.AccountNumber;
            target.AmountPastDue = source.AmountPastDue;
            target.Balance = source.Balance;
            target.Id = source.Id;
            target.InterestRate = source.InterestRate;
            target.LastTransactionAmount = source.LastTransactionAmount;
            target.LastTransactionDate = source.LastTransactionDate;
            target.MinimumPayment = source.MinimumPayment;
            target.Name = source.Name;
            target.NextPaymentAmount = source.NextPaymentAmount;
            target.NextPaymentDueDate = source.NextPaymentDueDate;
            target.NextPaymentInterest = source.NextPaymentInterest;
            target.NextPaymentPrincipal = source.NextPaymentPrincipal;
            target.PaymentSchedule = Convert(source.PaymentSchedule);
            target.ProjectedPaymentCompleteDate = source.ProjectedPaymentCompleteDate;
            target.TaxValueHouse = source.TaxValueHouse;
            target.Type = (DiscoveryLogic.DataServices.DataSources.AccountType)Enum.ToObject(typeof(AccountType), (int)source.Type);
            target.VisualPath = source.VisualPath;

            return target;
        }


        private static DiscoveryLogic.DataServices.DataSources.AmortizationSchedule Convert(AmortizationSchedule source)
        {
            DiscoveryLogic.DataServices.DataSources.AmortizationSchedule target = new DiscoveryLogic.DataServices.DataSources.AmortizationSchedule();
            target.AnnualInterestRate = source.AnnualInterestRate;
            target.FinalBalloonPayment = source.FinalBalloonPayment;
            target.PeriodicInterestRate = source.PeriodicInterestRate;
            target.PrincipalBorrowed = source.PrincipalBorrowed;
            target.RegularPaymentAmount = source.RegularPaymentAmount;
            target.ScheduleId = source.ScheduleId;
            target.StartDate = source.StartDate;
            target.TermInYears = source.TermInYears;
            target.TotalInterestAsPercentOfPrincipal = source.TotalInterestAsPercentOfPrincipal;
            target.TotalPayments = source.TotalPayments;
            target.TotalRepaid = source.TotalRepaid;

            return target;
        }
    }



    public class PortfolioService : WSProxy
    {

        public InvestmentPortfolio GetPortfolio()
        {
            System.Diagnostics.Debug.Assert(_portfolio != null);
            return _portfolio;
        }

        public void GetPortfolioAsync(GetPortfolioCompletedCallBack cb)
        {
            BankingClient bc = GetClient();
            bc.GetPortfolioCompleted += new EventHandler<GetPortfolioCompletedEventArgs>(bc_GetPortfolioCompleted);
            bc.GetPortfolioAsync();
            _callback = cb;
        }

        public delegate void GetPortfolioCompletedCallBack(GetPortfolioCompletedEventArgs e);
        public GetPortfolioCompletedCallBack _callback;

        protected static InvestmentPortfolio _portfolio;

        void bc_GetPortfolioCompleted(object sender, GetPortfolioCompletedEventArgs e)
        {
            _portfolio = Convert(e.Result);
            if (_callback != null)
                _callback(e);
        }

        private static InvestmentPortfolio Convert(InvestmentPortfolio source)
        {
            InvestmentPortfolio target = new InvestmentPortfolio();
            target.PortfolioValue = source.PortfolioValue;
            return target;
        }
    }



    public class BillPayService : WSProxy
    {
        public DiscoveryLogic.DataServices.DataSources.BillPayee[] GetPayees()
        {
            System.Diagnostics.Debug.Assert(_payees != null);
            return _payees;
        }

        static DiscoveryLogic.DataServices.DataSources.BillPayee[] _payees;

        public delegate void GetPayeesCallBack(GetPayeesCompletedEventArgs args);
        protected GetPayeesCallBack _GetPayeesCallBack;

        public void GetPayeesAsync(GetPayeesCallBack callback)
        {
            BankingClient bc = GetClient();
            this._GetPayeesCallBack = callback;
            bc.GetPayeesCompleted += new EventHandler<GetPayeesCompletedEventArgs>(bc_GetPayeesCompleted);
            bc.GetPayeesAsync();

        }

        void bc_GetPayeesCompleted(object sender, GetPayeesCompletedEventArgs e)
        {
            _payees = Convert(e.Result);
            if (_GetPayeesCallBack != null)
            {
                _GetPayeesCallBack(e);
            }
        }


        private static DiscoveryLogic.DataServices.DataSources.BillPayee[] Convert(BillPayee[] source)
        {
            DiscoveryLogic.DataServices.DataSources.BillPayee[] target = new DiscoveryLogic.DataServices.DataSources.BillPayee[source.Length];

            for (int i = 0; i < source.Length; i++)
            {
                target[i] = new DiscoveryLogic.DataServices.DataSources.BillPayee();
                target[i].AccountNumber = source[i].AccountNumber;
                target[i].IsRecurring = source[i].IsRecurring;
                target[i].Name = source[i].Name;
                target[i].History = new List<DiscoveryLogic.DataServices.DataSources.BillPayment>(Convert(source[i].History));
            }


            return target;
        }

        private static DiscoveryLogic.DataServices.DataSources.BillPayment[] Convert(BillPayment[] source)
        {
            DiscoveryLogic.DataServices.DataSources.BillPayment[] target = new DiscoveryLogic.DataServices.DataSources.BillPayment[source.Length];

            for (int i = 0; i < source.Length; i++)
            {
                target[i] = new DiscoveryLogic.DataServices.DataSources.BillPayment();
                // JAIMERTODO:
                target[i].Date = source[i].Date;
                target[i].FromAcc = source[i].FromAcc;
                target[i].Payment = source[i].Payment;
            }
            return target;
        }


    }

    public class AccountService : WSProxy
    {

        public delegate void GetAccountsCallBack(GetAccountsCompletedEventArgs args);
        protected GetAccountsCallBack _GetAccountsCompletedCallback;

        public void GetAccountsAsync(GetAccountsCallBack callback)
        {
            BankingClient bc = GetClient();
            this._GetAccountsCompletedCallback = callback;

            bc.GetAccountsCompleted += new EventHandler<GetAccountsCompletedEventArgs>(bc_GetAccountsCompleted);
            bc.GetAccountsAsync();

        }


        public static List<DiscoveryLogic.DataServices.DataSources.Account> Accounts
        {
            get
            {
                System.Diagnostics.Debug.Assert(_accounts != null);
                return _accounts;
            }
        }
        /* THIS DOES NOT WORK due to known inssues on M3 */
#if FALSE 
        public WSAccount[] GetAccountSync ()
        {
            BankingClient bc = new BankingClient(new BasicHttpBinding(), new EndpointAddress("http://jaimerxpold2/woodgrovebank/banking.svc"));
            // bc.GetAccountsCompleted += new EventHandler<GetAccountsCompletedEventArgs>(bc_GetAccountsCompleted);
            IAsyncResult result = bc.BeginGetAccounts(new AsyncCallback(accountsCallback), null);
            result.AsyncWaitHandle.WaitOne(); 
            WSAccount[] accounts = bc.EndGetAccounts(result);
            return accounts; 

        }
#endif

        void accountsCallback(IAsyncResult res)
        {
            System.Diagnostics.Debug.WriteLine("call back");

        }


        static List<DiscoveryLogic.DataServices.DataSources.Account> _accounts;

        void bc_GetAccountsCompleted(object sender, GetAccountsCompletedEventArgs e)
        {

            WS.Account[] source = e.Result;

            _accounts = new List<DiscoveryLogic.DataServices.DataSources.Account>();
            foreach (WS.Account account in source)
            {
                _accounts.Add(new DiscoveryLogic.DataServices.DataSources.Account(account.Id,
                               account.Name,
                               account.AccountNumber,
                               (DiscoveryLogic.DataServices.DataSources.AccountType)account.Type,
                               account.Balance,
                               account.MinimumPayment,
                               account.NextPaymentDueDate,
                               account.NextPaymentAmount,
                               account.VisualPath,
                               account.LastTransactionDate,
                               account.LastTransactionAmount)
                            );
            }

            if (this._GetAccountsCompletedCallback != null)
            {

                this._GetAccountsCompletedCallback(e);

            }
        }

    }

    public class LocalDataFiles
    {
        public static T LoadData<T>(string resource)
        {
            System.Runtime.Serialization.DataContractSerializer serializer = new System.Runtime.Serialization.DataContractSerializer(typeof(T));

            Stream stream = typeof(App).Assembly.GetManifestResourceStream(resource);
            T data = default(T);
            try
            {
                data = (T)serializer.ReadObject(stream);
            }
            catch (Exception ex1)
            {
                System.Diagnostics.Debug.WriteLine(ex1.Message);
            }
            stream.Close();


            return data;
        }

    }
}
